using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
using WeatherSystem.API.Data;
using WeatherSystem.API.Helpers;
using WeatherSystem.API.Models;
using WeatherSystem.API.Services;

namespace WeatherSystem.API.Controllers
{
    /// <summary>
    /// 天气数据API控制器
    /// </summary>
    [ApiController]
    [Route("api/[controller]")]
    [Authorize(Policy = "ReadOnlyOrHigher")]
    public class WeatherController : ControllerBase
    {
        private readonly WeatherDbContext _context;
        private readonly IWeatherService _weatherService;
        private readonly IDataCollectionService _dataCollectionService;
        private readonly IStatisticsService _statisticsService;
        private readonly ILogger<WeatherController> _logger;

        public WeatherController(
            WeatherDbContext context,
            IWeatherService weatherService,
            IDataCollectionService dataCollectionService,
            IStatisticsService statisticsService,
            ILogger<WeatherController> logger)
        {
            _context = context;
            _weatherService = weatherService;
            _dataCollectionService = dataCollectionService;
            _statisticsService = statisticsService;
            _logger = logger;
        }

        /// <summary>
        /// 获取所有城市列表
        /// </summary>
        [HttpGet("cities")]
        public async Task<ActionResult<List<City>>> GetCities()
        {
            try
            {
                var cities = await _context.Cities
                    .Where(c => c.IsActive)
                    .OrderBy(c => c.Name)
                    .ToListAsync();

                return Ok(cities);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取城市列表失败");
                return StatusCode(500, new { message = "获取城市列表失败", error = ex.Message });
            }
        }

        /// <summary>
        /// 分页查询天气数据
        /// </summary>
        [HttpGet]
        public async Task<ActionResult<PagedResult<object>>> GetWeatherData([FromQuery] WeatherDataQueryRequest request)
        {
            try
            {
                // 使用投影优化查询性能
                var query = _context.WeatherDataEntries
                    .Include(w => w.City)
                    .Include(w => w.Metrics.Where(m => m.Definition != null && m.Definition.IsActive))
                    .ThenInclude(m => m.Definition)
                    .AsNoTracking()
                    .AsQueryable();

                // 应用筛选条件
                if (request.CityId.HasValue)
                {
                    query = query.Where(w => w.CityId == request.CityId.Value);
                }

                if (request.StartDate.HasValue)
                {
                    query = query.Where(w => w.RecordedAt >= request.StartDate.Value);
                }

                if (request.EndDate.HasValue)
                {
                    query = query.Where(w => w.RecordedAt <= request.EndDate.Value);
                }

                // 应用排序（基于RecordedAt或City）
                query = request.SortBy?.ToLower() switch
                {
                    "city" => request.SortDirection?.ToLower() == "asc" 
                        ? query.OrderBy(w => w.City!.Name) 
                        : query.OrderByDescending(w => w.City!.Name),
                    _ => request.SortDirection?.ToLower() == "asc" 
                        ? query.OrderBy(w => w.RecordedAt) 
                        : query.OrderByDescending(w => w.RecordedAt)
                };

                // 获取总数
                var totalCount = await query.CountAsync();

                // 应用分页
                var weatherDataEntries = await query
                    .Skip((request.Page - 1) * request.PageSize)
                    .Take(request.PageSize)
                    .ToListAsync();

                // 转换为动态数据结构
                var data = new List<Dictionary<string, object>>();
                foreach (var entry in weatherDataEntries)
                {
                    var dict = new Dictionary<string, object>
                    {
                        ["id"] = entry.Id,
                        ["cityId"] = entry.CityId,
                        ["cityName"] = entry.City?.Name ?? "Unknown",
                        ["recordedAt"] = entry.RecordedAt,
                        ["createdAt"] = entry.CreatedAt,
                        ["source"] = entry.Source ?? ""
                    };

                    // 添加动态指标
                    foreach (var metric in entry.Metrics)
                    {
                        dict[metric.MetricKey] = ConvertRawValueToTyped(metric.RawValue, metric.DataType);
                    }

                    data.Add(dict);
                }

                var result = new PagedResult<object>
                {
                    Data = data.Cast<object>().ToList(),
                    TotalCount = totalCount,
                    Page = request.Page,
                    PageSize = request.PageSize
                };

                return Ok(result);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "分页查询天气数据时发生错误");
                return StatusCode(500, new { message = "服务器内部错误" });
            }
        }

        /// <summary>
        /// 获取指定城市的最新天气数据
        /// </summary>
        [HttpGet("current/{cityId}")]
        public async Task<ActionResult<object>> GetCurrentWeather(Guid cityId)
        {
            try
            {
                var weatherData = await _weatherService.GetLatestWeatherAsync(cityId);

                if (weatherData == null)
                {
                    return NotFound(new { message = "未找到该城市的天气数据" });
                }

                var result = await _weatherService.GetWeatherDataAsDictionaryAsync(weatherData.Id);
                result["cityName"] = weatherData.City?.Name ?? "Unknown";
                
                return Ok(result);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取城市天气数据时发生错误，城市ID: {CityId}", cityId);
                return StatusCode(500, new { message = "服务器内部错误" });
            }
        }

        /// <summary>
        /// 根据ID获取天气数据详情
        /// </summary>
        [HttpGet("{id}")]
        public async Task<ActionResult<object>> GetWeatherDataById(Guid id)
        {
            try
            {
                var result = await _weatherService.GetWeatherDataAsDictionaryAsync(id);
                if (result == null)
                {
                    return NotFound(new { message = "天气数据不存在" });
                }

                return Ok(result);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取天气数据详情时发生错误，ID: {Id}", id);
                return StatusCode(500, new { message = "服务器内部错误" });
            }
        }

        /// <summary>
        /// 获取指定城市的历史天气数据
        /// </summary>
        [HttpGet("history/{cityId}")]
        public async Task<ActionResult<List<Dictionary<string, object>>>> GetWeatherHistory(
            Guid cityId,
            [FromQuery] DateTime? startDate = null,
            [FromQuery] DateTime? endDate = null,
            [FromQuery] int limit = 100)
        {
            try
            {
                // 设置默认时间范围（最近7天）
                endDate ??= DateTime.UtcNow;
                startDate ??= endDate.Value.AddDays(-7);

                var weatherData = await _weatherService.GetWeatherHistoryAsDictionaryAsync(
                    cityId, startDate.Value, endDate.Value);

                // 应用limit限制
                if (limit > 0 && weatherData.Count > limit)
                {
                    weatherData = weatherData.Take(limit).ToList();
                }

                return Ok(weatherData);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取城市 {CityId} 历史天气失败", cityId);
                return StatusCode(500, new { message = "获取历史天气数据失败", error = ex.Message });
            }
        }

        /// <summary>
        /// 获取指定城市的每日统计数据（动态EAV结构）
        /// </summary>
        [HttpGet("statistics/daily/{cityId}")]
        public async Task<ActionResult<Dictionary<string, object>>> GetDailyStatistics(
            Guid cityId,
            [FromQuery] DateTime? date = null)
        {
            try
            {
                date ??= DateTime.Today;
                
                var statistics = await _statisticsService.GetDailyStatisticsAsync(
                    cityId, date.Value);

                if (statistics == null || !statistics.Any())
                {
                    return NotFound(new { message = "未找到该日期的统计数据" });
                }

                return Ok(statistics);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取城市 {CityId} 每日统计失败", cityId);
                return StatusCode(500, new { message = "获取统计数据失败", error = ex.Message });
            }
        }

        /// <summary>
        /// 获取指定城市的统计数据范围（动态EAV结构）
        /// </summary>
        [HttpGet("statistics/range/{cityId}")]
        public async Task<ActionResult<List<Dictionary<string, object>>>> GetStatisticsRange(
            Guid cityId,
            [FromQuery] DateTime startDate,
            [FromQuery] DateTime endDate)
        {
            try
            {
                if (startDate > endDate)
                {
                    return BadRequest(new { message = "开始日期不能大于结束日期" });
                }

                var statistics = await _statisticsService.GetStatisticsRangeAsync(
                    cityId, startDate, endDate);

                return Ok(statistics);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取城市 {CityId} 统计范围失败", cityId);
                return StatusCode(500, new { message = "获取统计数据失败", error = ex.Message });
            }
        }

        /// <summary>
        /// 获取天气趋势数据（动态EAV结构）
        /// </summary>
        [HttpGet("trend/{cityId}")]
        public async Task<ActionResult<object>> GetWeatherTrend(
            Guid cityId,
            [FromQuery] int days = 7)
        {
            try
            {
                if (days <= 0 || days > 365)
                {
                    return BadRequest(new { message = "天数必须在1-365之间" });
                }

                var trendData = await _statisticsService.GetWeatherTrendAsync(cityId, days);
                return Ok(trendData);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取城市 {CityId} 天气趋势失败", cityId);
                return StatusCode(500, new { message = "获取趋势数据失败", error = ex.Message });
            }
        }

        /// <summary>
        /// 获取城市对比数据（动态EAV结构）
        /// </summary>
        [HttpPost("comparison")]
        public async Task<ActionResult<List<Dictionary<string, object>>>> GetCityComparison(
            [FromBody] CityComparisonRequest request)
        {
            try
            {
                if (request.CityIds == null || !request.CityIds.Any())
                {
                    return BadRequest(new { message = "城市ID列表不能为空" });
                }

                if (request.CityIds.Count > 10)
                {
                    return BadRequest(new { message = "最多只能对比10个城市" });
                }

                var comparisonData = await _statisticsService.GetCityComparisonAsync(
                    request.CityIds, DateTime.Today);

                return Ok(comparisonData);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取城市对比数据失败");
                return StatusCode(500, new { message = "获取对比数据失败", error = ex.Message });
            }
        }

        /// <summary>
        /// 添加天气数据（动态结构）
        /// </summary>
        [HttpPost]
        [Authorize(Policy = "UserOrAdmin")]
        public async Task<ActionResult<object>> CreateWeatherData([FromBody] CreateDynamicWeatherDataRequest request)
        {
            try
            {
                // 验证城市是否存在
                var cityExists = await _context.Cities.AnyAsync(c => c.Id == request.CityId && c.IsActive);
                if (!cityExists)
                {
                    return BadRequest(new { message = "指定的城市不存在或已禁用" });
                }

                // 创建WeatherDataEntry
                var weatherDataEntry = new WeatherDataEntry
                {
                    CityId = request.CityId,
                    RecordedAt = request.RecordedAt,
                    Source = request.Source ?? "Manual"
                };

                // 创建MetricValue记录
                var metricValues = new List<MetricValue>();
                if (request.Metrics != null)
                {
                    var validMetrics = await _context.MetricDefinitions
                        .Where(m => m.IsActive)
                        .ToListAsync();

                    foreach (var kvp in request.Metrics)
                    {
                        var metricDef = validMetrics.FirstOrDefault(m => m.Key == kvp.Key);
                        if (metricDef != null)
                        {
                            metricValues.Add(new MetricValue
                            {
                                WeatherDataEntryId = weatherDataEntry.Id,
                                MetricKey = kvp.Key,
                                RawValue = kvp.Value?.ToString() ?? string.Empty,
                                DataType = metricDef.DataType
                            });
                        }
                    }
                }

                weatherDataEntry.Metrics = metricValues;
                _context.WeatherDataEntries.Add(weatherDataEntry);
                await _context.SaveChangesAsync();

                _logger.LogInformation("成功添加天气数据，ID: {Id}", weatherDataEntry.Id);

                return CreatedAtAction(
                    nameof(GetCurrentWeather),
                    new { cityId = weatherDataEntry.CityId },
                    new { id = weatherDataEntry.Id, message = "天气数据创建成功" }
                );
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建天气数据时发生错误");
                return StatusCode(500, new { message = "服务器内部错误" });
            }
        }

        /// <summary>
        /// 批量添加天气数据（动态结构）
        /// </summary>
        [HttpPost("batch")]
        [Authorize(Policy = "UserOrAdmin")]
        public async Task<ActionResult<object>> CreateWeatherDataBatch([FromBody] List<CreateDynamicWeatherDataRequest> requests)
        {
            try
            {
                if (requests == null || !requests.Any())
                {
                    return BadRequest(new { message = "请求数据不能为空" });
                }

                if (requests.Count > 100)
                {
                    return BadRequest(new { message = "批量操作最多支持100条数据" });
                }

                var results = await _weatherService.CreateWeatherDataBatchAsync(requests);
                
                return Ok(new
                {
                    message = "批量创建成功",
                    createdCount = results.Count,
                    ids = results
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量创建天气数据时发生错误");
                return StatusCode(500, new { message = "服务器内部错误" });
            }
        }

        /// <summary>
        /// 更新天气数据（动态结构）
        /// </summary>
        [HttpPut("{id}")]
        [Authorize(Policy = "UserOrAdmin")]
        public async Task<ActionResult<object>> UpdateWeatherData(Guid id, [FromBody] UpdateDynamicWeatherDataRequest request)
        {
            try
            {
                var result = await _weatherService.UpdateWeatherDataAsync(id, request);
                if (!result)
                {
                    return NotFound(new { message = "天气数据不存在" });
                }

                return Ok(new { message = "天气数据更新成功" });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新天气数据时发生错误，ID: {Id}", id);
                return StatusCode(500, new { message = "服务器内部错误" });
            }
        }

        /// <summary>
        /// 删除天气数据
        /// </summary>
        [HttpDelete("{id}")]
        [Authorize(Roles = "Admin")]
        public async Task<ActionResult<object>> DeleteWeatherData(Guid id)
        {
            try
            {
                var result = await _weatherService.DeleteWeatherDataAsync(id);
                if (!result)
                {
                    return NotFound(new { message = "天气数据不存在" });
                }

                return Ok(new { message = "天气数据删除成功" });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "删除天气数据时发生错误，ID: {Id}", id);
                return StatusCode(500, new { message = "服务器内部错误" });
            }
        }

        /// <summary>
        /// 手动触发数据采集
        /// </summary>
        [HttpPost("collect")]
        [Authorize(Roles = "Admin")]
        public async Task<ActionResult> TriggerDataCollection()
        {
            try
            {
                await _dataCollectionService.CollectWeatherDataAsync();
                return Ok(new { message = "数据采集已触发" });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "手动触发数据采集失败");
                return StatusCode(500, new { message = "数据采集失败", error = ex.Message });
            }
        }

        /// <summary>
        /// 获取数据采集状态
        /// </summary>
        [HttpGet("collection/status")]
        public async Task<ActionResult> GetCollectionStatus()
        {
            try
            {
                var isEnabled = await _dataCollectionService.IsCollectionEnabledAsync();
                var lastCollectionTime = await _dataCollectionService.GetLastCollectionTimeAsync();

                return Ok(new
                {
                    enabled = isEnabled,
                    lastCollectionTime = lastCollectionTime,
                    status = isEnabled ? "运行中" : "已停止"
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取数据采集状态失败");
                return StatusCode(500, new { message = "获取采集状态失败", error = ex.Message });
            }
        }

        /// <summary>
        /// 设置数据采集状态
        /// </summary>
        [HttpPost("collection/toggle")]
        [Authorize(Roles = "Admin")]
        public async Task<ActionResult> ToggleDataCollection([FromBody] ToggleCollectionRequest request)
        {
            try
            {
                await _dataCollectionService.SetCollectionStatusAsync(request.Enabled);
                
                var status = request.Enabled ? "启用" : "禁用";
                return Ok(new { message = $"数据采集已{status}" });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "设置数据采集状态失败");
                return StatusCode(500, new { message = "设置采集状态失败", error = ex.Message });
            }
        }

        /// <summary>
        /// 生成每日统计数据
        /// </summary>
        [HttpPost("statistics/generate")]
        [Authorize(Roles = "Admin")]
        public async Task<ActionResult> GenerateStatistics([FromQuery] DateTime? date = null)
        {
            try
            {
                date ??= DateTime.Today.AddDays(-1); // 默认生成昨天的统计
                
                await _statisticsService.GenerateDailyStatisticsAsync(date.Value);
                
                return Ok(new { message = $"已生成 {date.Value:yyyy-MM-dd} 的统计数据" });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "生成统计数据失败");
                return StatusCode(500, new { message = "生成统计数据失败", error = ex.Message });
            }
        }

        /// <summary>
        /// 获取数据采集日志
        /// </summary>
        [HttpGet("logs")]
        public async Task<ActionResult<List<DataCollectionLog>>> GetCollectionLogs(
            [FromQuery] int limit = 50)
        {
            try
            {
                var logs = await _context.DataCollectionLogs
                    .OrderByDescending(l => l.ExecutionTime)
                    .Take(limit)
                    .ToListAsync();

                return Ok(logs);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取采集日志失败");
                return StatusCode(500, new { message = "获取日志失败", error = ex.Message });
            }
        }

        /// <summary>
        /// 模拟天气数据生成 - 为数据库中所有城市生成模拟数据（动态EAV结构）
        /// </summary>
        [HttpPost("simulate")]
        [AllowAnonymous]
        public async Task<ActionResult<object>> SimulateWeatherData([FromBody] SimulateWeatherRequest request)
        {
            try
            {
                // 获取数据库中所有活跃的城市
                var cities = await _context.Cities
                    .Where(c => c.IsActive)
                    .ToListAsync();

                if (!cities.Any())
                {
                    return BadRequest(new { message = "数据库中没有活跃的城市数据" });
                }

                // 获取活跃的指标定义
                var metricDefinitions = await _context.MetricDefinitions
                    .Where(m => m.IsActive)
                    .ToListAsync();

                var random = new Random();
                var weatherDataEntries = new List<WeatherDataEntry>();
                var generatedCount = 0;

                // 为每个城市生成指定数量的模拟天气数据
                foreach (var city in cities)
                {
                    for (int i = 0; i < (request.Count ?? 1); i++)
                    {
                        var weatherDataEntry = new WeatherDataEntry
                        {
                            CityId = city.Id,
                            RecordedAt = DateTime.UtcNow.AddMinutes(-random.Next(0, 1440)), // 随机时间（过去24小时内）
                            Source = "Simulated"
                        };

                        // 生成动态指标值
                        var metricValues = new List<MetricValue>();
                        foreach (var metricDef in metricDefinitions)
                        {
                            string rawValue = metricDef.Key switch
                            {
                                "temperature" => (request.BaseTemperature + (random.NextDouble() - 0.5) * 20).ToString("F2"),
                                "humidity" => random.Next(20, 95).ToString(),
                                "pressure" => (1013 + (random.NextDouble() - 0.5) * 60).ToString("F2"),
                                "windSpeed" => (random.NextDouble() * 20).ToString("F2"),
                                "windDirection" => random.Next(0, 360).ToString(),
                                "visibility" => random.Next(1, 50).ToString(),
                                "uvIndex" => random.Next(0, 12).ToString(),
                                "weatherCondition" => GetRandomWeatherCondition(random),
                                _ => "0"
                            };

                            metricValues.Add(new MetricValue
                            {
                                WeatherDataEntryId = weatherDataEntry.Id,
                                MetricKey = metricDef.Key,
                                RawValue = rawValue,
                                DataType = metricDef.DataType
                            });
                        }

                        weatherDataEntry.Metrics = metricValues;
                        weatherDataEntries.Add(weatherDataEntry);
                        generatedCount++;
                    }
                }

                // 批量保存到数据库
                _context.WeatherDataEntries.AddRange(weatherDataEntries);
                await _context.SaveChangesAsync();

                _logger.LogInformation("模拟天气数据批量生成成功，城市数量: {CityCount}, 总数据条数: {DataCount}", 
                    cities.Count, generatedCount);

                return Ok(new
                {
                    message = "模拟天气数据生成成功",
                    cityCount = cities.Count,
                    totalDataGenerated = generatedCount,
                    baseTemperature = request.BaseTemperature,
                    countPerCity = request.Count ?? 1,
                    cities = cities.Select(c => new { c.Id, c.Name, c.Country }).ToList()
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "模拟天气数据生成失败");
                return StatusCode(500, new { message = "模拟天气数据生成失败", error = ex.Message });
            }
        }

        /// <summary>
        /// 获取随机天气状况
        /// </summary>
        private string GetRandomWeatherCondition(Random random)
        {
            var conditions = new[] { "晴朗", "多云", "阴天", "小雨", "中雨", "雷阵雨", "雪", "雾" };
            return conditions[random.Next(conditions.Length)];
        }

        /// <summary>
        /// 将原始值转换为相应的类型
        /// </summary>
        private object ConvertRawValueToTyped(string rawValue, string dataType)
        {
            return dataType.ToLower() switch
            {
                "decimal" => decimal.TryParse(rawValue, out var d) ? d : 0m,
                "int" => int.TryParse(rawValue, out var i) ? i : 0,
                "boolean" => bool.TryParse(rawValue, out var b) && b,
                _ => rawValue
            };
        }
    }


    /// <summary>
    /// 切换采集状态请求模型
    /// </summary>
    public class ToggleCollectionRequest
    {
        public bool Enabled { get; set; }
    }

    /// <summary>
    /// 天气数据查询请求模型
    /// </summary>
    public class WeatherDataQueryRequest
    {
        public Guid? CityId { get; set; }
        public DateTime? StartDate { get; set; }
        public DateTime? EndDate { get; set; }
        public string? Source { get; set; }
        public string? SortBy { get; set; } = "recordedAt";
        public string? SortDirection { get; set; } = "desc";
        public int Page { get; set; } = 1;
        public int PageSize { get; set; } = 20;
    }


    /// <summary>
    /// 模拟天气数据请求模型
    /// </summary>
    public class SimulateWeatherRequest
    {
        /// <summary>
        /// 基础温度（摄氏度）
        /// </summary>
        public double BaseTemperature { get; set; } = 20.0;
        
        /// <summary>
        /// 每个城市生成的数据条数
        /// </summary>
        public int? Count { get; set; } = 1;
    }

}